import agent from '../agent/index.js';
import { TerminalType } from '../type.js';
import { v4 as uuidv4 } from 'uuid';
import { logger } from '../tools/index.js';
import { createHook } from './hook-server.js';
import { translateVoiceFile } from '../service/nls.js';
const wechatServerPort = process.env.WECHAT_SERVER_PORT || 8805;
const wechatCallbackPort = process.env.WECHAT_CALLBACK_PORT || 3008;
const bindWxId = process.env.WECHAT_BIND_WXID;

const processWechatMsg = (text) => {
    if (!text) return text;
    return text.replaceAll('**', '');
}

/**
 * 构建上下文
 */
const buildWechatContext = (sender, room, currentUser, atWxUsers) => {
    return {
        requestId: uuidv4(),
        terminal: TerminalType.WECHAT,
        bot: {
            id: currentUser.wxid,
            name: currentUser.nick
        },
        user: {
            id: sender.id,
            name: sender.name,
            avatarUrl: sender.avatarUrl,
            atWxUsers: atWxUsers
        },
        book: {
            id: room.id,
            name: room.name
        },
        files: []
    }
}

/**
 * 转换微信消息为文本
 */
const converterToText = async wechatMsg => {
    if (wechatMsg.msgType === 1) {
        // 文本消息
        return wechatMsg.msg;
    } else if (wechatMsg.msgType === 34) {
        // 语音消息
        // try {
        //     const sourceMsg = wechatMsg.msg;
        //     return await translateVoiceFile();
        // } catch(err) {
        //     logger.error("识别微信语言消息失败, sourceMsg: %s, errMsg: %s", sourceMsg, err);
        // }
    } else {
        return '';
    }
}

export async function createRobot() {
    logger.info('create wechat robot...');
    const wechatRobot = await createHook({
        bindWxId: bindWxId,
        serverPort: wechatServerPort,
        callbackPort: wechatCallbackPort,
        onMessage: async (msg) => {
            if (msg.msgType !== 1) {
                // 不处理非文本消息
                logger.warn("不处理非文本/语音消息");
                return;
            }
            if (msg.fromType !== 2) {
                // 不处理非群组消息
                logger.warn("不处理非群组消息");
                return;
            }
            if (msg.msgSource === 1) {
                // 不处理自己给自己发的消息
                logger.warn("不处理自己给自己发的消息");
                return;
            }

            const text = await converterToText(msg);
            const currentUser = await wechatRobot.getCurrentUser();
            const currentUserName = currentUser.nick;
            const senderWxId = msg.finalFromWxid;
            const roomWxId = msg.fromWxid;
            const atWxidList = msg.atWxidList;

            if (!text) {
                // 不处理空消息
                logger.warn("不处理空消息");
                return;
            }

            if (msg.msgType === 1) {
                if (text.indexOf(`@${currentUserName}`) < 0) {
                    // 不处理群组中不是艾特自己的消息
                    logger.warn("不处理群组中不是艾特自己的消息");
                    return;
                }
            } else if (msg.msgType === 34) {
                if (text.indexOf(`${currentUserName}`) < 0) {
                    // 不处理语言中没有提到自己的消息
                    logger.warn("不处理语言中没有提到自己的消息");
                    return;
                }
            }


            logger.info(`wechat robot action message, msg = ${text}`);

            try {
                await sendWxMessage(roomWxId, `小钱钱正在思考中，请稍后...`);
                const room = await wechatRobot.getRoom(roomWxId);
                const sender = await wechatRobot.getUser(senderWxId);
                const atWxUserList = await getWxUsers(atWxidList);
                if (!room) {
                    throw new Error('获取群组信息失败...');
                }
                if (!sender) {
                    throw new Error('获取用户信息失败...');
                }
                const wechatCtx = buildWechatContext({ id: senderWxId, name: sender.nick, avatarUrl: sender.avatarMinUrl }, { id: roomWxId, name: room.nick }, currentUser, atWxUserList);
                const res = await agent([{ role: 'user', content: text }], () => { }, wechatCtx);
                if (wechatCtx.agentModuleName === '用户模块') {
                    await sendWxMessage(roomWxId, `小钱钱处理完成，涉及用户隐私信息，已私聊发送。`, atWxUserList);
                    await sendWxMessage(senderWxId, processWechatMsg(res.output.text));
                    return;
                }
                if (wechatCtx.files.length > 0) {
                    for (const sendFile of wechatCtx.files) {
                        await wechatRobot.sendFile(roomWxId, sendFile.name, sendFile.buffer);
                    }
                }

                // 别说话
                if (wechatCtx.doNotTalk) {
                    return;
                }
                await sendWxMessage(roomWxId, processWechatMsg(res.output.text));
            } catch (err) {
                logger.error(`wechat robot action message error`, err);
                await sendWxMessage(roomWxId, `抱歉这个问题我无法回答，参考信息: ${err}`);
            }
        }
    });

    const sendWxMessage = async (roomId, message, atWxUserList) => {
        message = wapperAtWxid(message, atWxUserList);
        await wechatRobot.sendMessage(roomId, message);
    }

    const getWxUser = async (accountNo) => {
        return await wechatRobot.getUser(accountNo);
    }

    const getWxUsers = async (accountNoList = []) => {
        if (!Array.isArray(accountNoList)) {
            logger.warn(`accountNoList is not array, accountNoList = ${JSON.stringify(accountNoList)}`);
            return [];
        }
        const result = [];
        for (const wxid of accountNoList) {
            const wxUser = await getWxUser(wxid);
            if (wxUser) {
                result.push({
                    id: wxUser.wxid,
                    name: wxUser.nick
                });
            }
        }
        return result;
    }

    const wapperAtWxid = (sourceMessage, atWxUserList = []) => {
        return `${(atWxUserList || []).map(({ id, name }) => {
            return `[@,wxid=${id},nick=${name},isAuto=true]`
        }).join('\n')}${sourceMessage}`;
    }

    return {
        sendWxMessage,
        getUserRooms: wechatRobot.getUserRooms,
        getWxUsers,
        getWxUser
    };
}